//------------------------------------------------------------------------------ 
//      Copyright (c) 2004-2009, Be Nanashi-San 
// 
//      Permission is hereby granted, free of charge, to any person obtaining a 
//      copy of this software and associated documentation files (the "Software"), 
//      to deal in the Software without restriction, including without limitation 
//      the rights to use, copy, modify, merge, publish, distribute, sublicense, 
//      and/or sell copies of the Software, and to permit persons to whom the 
//      Software is furnished to do so, subject to the following conditions: 
// 
//      The above copyright notice and this permission notice shall be included in 
//      all copies or substantial portions of the Software. 
// 
//      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
//      IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
//      FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
//      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
//      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
//      FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
//      DEALINGS IN THE SOFTWARE. 
// 
//      File Name:   BoardItem.cpp
//      Author:      Be Nanashi-San 
//      Description: BBS Board list display class. 
//------------------------------------------------------------------------------

/******************************************************************************
This source code is modified from Haiku's ListItem.cpp made by Ulrich Wimboeck.
*******************************************************************************/
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//	Copyright (c) 2001-2002, OpenBeOS
//
//	Permission is hereby granted, free of charge, to any person obtaining a
//	copy of this software and associated documentation files (the "Software"),
//	to deal in the Software without restriction, including without limitation
//	the rights to use, copy, modify, merge, publish, distribute, sublicense,
//	and/or sell copies of the Software, and to permit persons to whom the
//	Software is furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in
//	all copies or substantial portions of the Software.
//
//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//	DEALINGS IN THE SOFTWARE.
//
//	File Name:		ListItem.cpp
//	Author:			Ulrich Wimboeck
//					Marc Flerackers (mflerackers@androme.be)
//	Description:	BListView represents a one-dimensional list view.
//------------------------------------------------------------------------------

#include "BoardItem.h"
#include "balls.h"
#include <View.h>
#include <Message.h>
#include <Bitmap.h>
#include <string.h>
#include <stdlib.h>

BBitmap * BoardItem::fRedball = NULL; 
BBitmap * BoardItem::fBlueball = NULL; 
BBitmap * BoardItem::fYellowball = NULL; 
uint32 BoardItem::fCount = 0; 
//20060627:BString -> char

//////////////////////////////////////////////////////////////////////
// InitBitmap
//
//
//////////////////////////////////////////////////////////////////////
void
BoardItem::InitBitmap()
{
	fRedball = new BBitmap(BRect(0, 0, kImageWidth - 1, kImageHeight - 1),  B_CMAP8);
	fRedball->SetBits(kRedBall, sizeof(kRedBall), 0, B_CMAP8);
	fBlueball = new BBitmap(BRect(0 ,0, kImageWidth - 1, kImageHeight - 1),  B_CMAP8);
	fBlueball->SetBits(kBlueBall, sizeof(kBlueBall), 0, B_CMAP8);
	fYellowball = new BBitmap(BRect(0, 0, kImageWidth - 1, kImageHeight - 1),  B_CMAP8);
	fYellowball->SetBits(kYellowBall, sizeof(kYellowBall), 0, B_CMAP8);
}
//////////////////////////////////////////////////////////////////////
// DeleteBitmap
//
//
//////////////////////////////////////////////////////////////////////
void
BoardItem::DeleteBitmap()
{
	delete fRedball;
	delete fBlueball;
	delete fYellowball;	
}
//////////////////////////////////////////////////////////////////////
// BoardItem
//
//
//////////////////////////////////////////////////////////////////////
BoardItem::BoardItem(const char *label, const char *uri, int32 type, uint32 level, bool expanded)
:BListItem(level, expanded),
fLabel(NULL),
fUri(NULL),
fBaselineOffset(0),
fType(type)
{	
	this->SetLabel(label);
	this->SetUri(uri);

	if(fCount == 0) InitBitmap();
	fCount++;
}
//////////////////////////////////////////////////////////////////////
// BoardItem
//
//
//////////////////////////////////////////////////////////////////////
BoardItem::BoardItem(BMessage *archive)
:BListItem(archive),
fLabel(NULL),
fUri(NULL),
fBaselineOffset(0),
fType(0)
{
	const char *string;

	if (archive->FindString("_label", &string) == B_OK)
		this->SetLabel(string);
	if (archive->FindString("_uri", &string) == B_OK)
		this->SetUri(string);

	int32 i;
	if (archive->FindInt32("_icontypes", &i) == B_OK)
		fType = i;

	if(fCount == 0) InitBitmap();
	fCount++;
}
//////////////////////////////////////////////////////////////////////
// ~BoardItem
//
//
//////////////////////////////////////////////////////////////////////
BoardItem::~BoardItem()
{
	free(fLabel);
	free(fUri);
	fCount--;
	if(fCount == 0) DeleteBitmap();
}
//////////////////////////////////////////////////////////////////////
// Instantiate
//
//
//////////////////////////////////////////////////////////////////////
BArchivable*
BoardItem::Instantiate(BMessage *archive)
{
	if (validate_instantiation(archive, "BoardItem")){
		return new BoardItem(archive);
	}else{
		return NULL;
	}
}
//////////////////////////////////////////////////////////////////////
// Archive
//
//
//////////////////////////////////////////////////////////////////////
status_t
BoardItem::Archive(BMessage *archive, bool deep) const
{
	status_t status = BListItem::Archive(archive, deep);

	if (status == B_OK){
		archive->AddString("_label", fLabel);
		archive->AddString("_uri", fUri);
		archive->AddInt32("_icontypes", fType);
	}
	return status;
}
//////////////////////////////////////////////////////////////////////
// DrawItem
//
//
//////////////////////////////////////////////////////////////////////
void
BoardItem::DrawItem(BView *owner, BRect frame, bool complete)
{
	if (fLabel == NULL)
		return;

	rgb_color highColor = owner->HighColor();
	rgb_color lowColor = owner->LowColor();

	if (IsSelected() || complete){
		if (IsSelected()){
			owner->SetHighColor(tint_color(lowColor, B_DARKEN_2_TINT));
			owner->SetLowColor(owner->HighColor()); //20050729追加。
		}else{
			owner->SetHighColor(lowColor);
		}
		owner->FillRect(frame);
	}

	owner->MovePenTo(frame.LeftTop());
	owner->SetDrawingMode(B_OP_OVER);

	BBitmap *map;
	switch (fType){
		case BOARD_SELECTED:
			map = fRedball;
			break;
		case BOARD_NORMAL:
			map = fBlueball;
			break;
		case BOARD_CATEGORY:
			map = fYellowball;
			break;
		default:
			map = fYellowball;
	}
	owner->DrawBitmapAsync(map);
	
	owner->MovePenTo(frame.left + kImageWidth + 2, frame.top + fBaselineOffset);


	owner->SetDrawingMode(B_OP_COPY);
	const rgb_color black = {0, 0, 0, 255};

	if (!IsEnabled()){
		owner->SetHighColor(tint_color(black, B_LIGHTEN_2_TINT));
	}else{
		owner->SetHighColor(black);
	}
	owner->DrawString(fLabel);

	owner->SetHighColor(highColor);
	owner->SetLowColor(lowColor);
}
//////////////////////////////////////////////////////////////////////
// Update
//
//
//////////////////////////////////////////////////////////////////////
void
BoardItem::Update(BView *owner, const BFont *font)
{
	if (fLabel)	{
		BListItem::SetWidth(owner->StringWidth(fLabel) + kImageWidth);
	}else{
		BListItem::SetWidth(kImageWidth);
	}
	
	font_height fheight;

	font->GetHeight(&fheight);
	fBaselineOffset = fheight.ascent + fheight.leading;
	float h = ceil(fheight.ascent + fheight.descent + fheight.leading) + 4.0;
	BListItem::SetHeight( h > kImageHeight ? h : kImageHeight);
}
//////////////////////////////////////////////////////////////////////
// SetText
//
//
//////////////////////////////////////////////////////////////////////
void
BoardItem::SetLabel(const char *label)
{
	free(fLabel);
	fLabel = NULL;
	
	if (label)
		fLabel = strdup(label);
}
//////////////////////////////////////////////////////////////////////
// SetUri
//
//
//////////////////////////////////////////////////////////////////////
void
BoardItem::SetUri(const char *uri)
{
	free(fUri);
	fUri = NULL;
	
	if (uri)
		fUri = strdup(uri);
}
